package p2psvideo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import p2psvideo.Interfaces.OnFileDownloadCreatedListener;
import p2psvideo.Interfaces.OnFileDownloadFailedListener;
import p2psvideo.Interfaces.OnFileDownloadFinishedListener;
import p2psvideo.Interfaces.OnFileDownloadProgressListener;
import p2psvideo.Interfaces.OnFileListChangedListener;
import p2psvideo.Interfaces.OnHttpResponse;
import p2psvideo.Interfaces.OnServiceReadyListener;

public class P2PSMgr {
	///不进行下载, 当缓存空间不足时，后台程序可能进行文件回收释放磁盘空间
	static public final int DOWNLOAD_TYPE_NONE = 0;
	///暂停下载，直到下载类型设置为DOWNLOAD_TYPE_NORMAL或者DOWNLOAD_TYPE_ASAP
	static public final int DOWNLOAD_TYPE_PAUSE = 1;
	///普通下载, 下载进程以近乎实时播放的速度下载数据，如果有P2P资源会尽量考虑从P2P网络进行下载
	static public final int DOWNLOAD_TYPE_NORMAL = 2;
	///尽快下载，下载进程以尽可能快的速度下载数据，此时基本不考虑P2P资源
	static public final int DOWNLOAD_TYPE_ASAP = 3;

	///禁止下载
	static public final int ALLOW_DOWNLOAD_DENY = 0;
	///允许在WIFI或者以太网条件下下载
	static public final int ALLOW_DOWNLOAD_WIFI = 1;
	///允许在任何网络下下载
	static public final int ALLOW_DOWNLOAD_ALL = 2;

	static class ReferenceCount
	{
		int count;
		ReferenceCount(int c)
		{
			count = c;
		}
		void inc() {
			count++;
		}
		int dec()
		{
			count--;
			return count;
		}
	}

	///子流信息
	public static class P2PFileSubStreamInfo
	{
		///子流ID
		public String vsid;
		///清晰度配置名
		public String definition;
		///语言名
		public String lang;
		///文件格式名
		public String format;
		///视频编码类型
		public String videoCodec;
		///音频编码类型
		public String audioCodec;
		///如果文件时外部文件时的地址
		public String externalLink;
		///宽度
		public int width;
		///高度
		public int height;
		///码率kbps
		public int dataRate;
		///帧率
		public int fps;
	}
	///P2PS 文件信息
	public static class P2PSFileInfo
	{
		///唯一标识这个文件的ID
		public String vsid;
		///该视频子流所属的视频ID
		public String vid;
		///是否是直播, 否则是点播
		public boolean live;
		///是否正在播放中
		public boolean forPlay;
		///是否正在下载中
		public boolean forDownload;
		///下载完成百分比
		public int percent;
		///下载策略
		public int downloadPolicy;
		///上次播放或者创建下载时的时间戳, 自1970-1-1起的时间戳，单位秒
		public long useTime;
		///创建下载时设置的应用程序自定义的数据
		public String extra;
		///在磁盘中的位置
		public String root;
		///在磁盘中的大小
		public long onDiskSize;
		///整个文件的大小
		public long totalFileSize;
		///文件长度
		public int duration;
		///父格式是什么
		public int pformat;
		///子格式是什么
		public int format;
		///视频URL
		public String urls;
		///视频串流URL
		public String streamers;
		///视频标题
		public String name;
		///视频标签
		public String tags;
		///视频描述
		public String description;
		///视频页面地址
		public String page;
		///视频来源
		public String fromType;
		///视频缩略图地址前缀
		public String thumbnail;
		///章节信息
		public String captions;
		///电影级别
		public int movieLevel;
		///电影级别名
		public String movieLevelName;
		///视频评分
		public int rate;
		///视频评分人数
		public int rateCount;
		///子流信息
		public P2PFileSubStreamInfo[] streams;
	}

	static class OnCreateDownload
	{
		OnFileDownloadCreatedListener onCreate;
		OnFileDownloadFailedListener onFailed;
	}

	private Context _appCtx;
	private ServiceConnection _svcConn;
	private IP2PSRemote _intf;
	private Handler _handler;
	private OnFileListChangedListener _onFileListChanged;
	private OnFileDownloadProgressListener _onFileDownloadProgress;
	private List<OnFileDownloadFinishedListener> _onFileDownloadFinisheds;
	private OnFileDownloadFinishedListener _onFileDownloadFinished;
	private OnServiceReadyListener _onServiceReady;
	private Map<String, OnCreateDownload> _downloadCallbacks = new HashMap<String, OnCreateDownload>();
	private Map<OnHttpResponse, ReferenceCount> _readFileCB = new HashMap<OnHttpResponse, ReferenceCount>();
	private boolean _enableLocalStorage;
	private boolean _inAppStorage;

	public P2PSMgr(Context appCtx) {
		_appCtx = appCtx;
		_handler = new Handler();
		_enableLocalStorage = true;
		_inAppStorage = false;
		init();
	}
	public P2PSMgr(Context appCtx, boolean enableLocalStorage, boolean inAppStorage) {
		_appCtx = appCtx;
		_handler = new Handler();
		_enableLocalStorage = enableLocalStorage;
		_inAppStorage = inAppStorage;
		init();
	}
	private void init()
	{
		if (_intf != null) {
			Log.e("P2PSService", "Service is already there");
			return;
		}
		Log.v("P2PSService", "Initializing P2PService for download");
		Intent startIntent = new Intent(_appCtx, P2PSService.class);
		_appCtx.startService(startIntent);
		_svcConn = new ServiceConnection() {
			@Override
			public void onServiceConnected(ComponentName arg0, IBinder arg1) {
				try {
					_intf = IP2PSRemote.Stub.asInterface(arg1);
				} catch(Throwable e) {
					e.printStackTrace();
					Log.e("P2PSService", "Failed to bind to service interface, restart in 5s");
					close();
					_handler.postDelayed(new Runnable() {
						@Override
						public void run() {
							init();
						}
					}, 5000);
					return;
				}
				try {
					_intf.enableLocalStorage(_enableLocalStorage, _inAppStorage);
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				//执行下载策略，但不修改
				try {
					_intf.setBackground(false);
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				try {
					_intf.setOnFileListChangedListener(new p2psvideo.aidl.OnFileListChangedListener.Stub() {
						@Override
						public void onChanged(final String vsid) throws RemoteException {
							_handler.post(new Runnable() {
								@Override
								public void run() {
									if (_onFileListChanged != null) {
										_onFileListChanged.onChanged(vsid);
									}
								}
							});
						}
					});
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				try {
					_intf.setOnFileDownloadProgressListener(new p2psvideo.aidl.OnFileDownloadProgressListener.Stub() {
						@Override
						public void onProgress(final String vsid, final int percent) throws RemoteException {
							_handler.post(new Runnable() {
								@Override
								public void run() {
									if (_onFileDownloadProgress != null) {
										_onFileDownloadProgress.onProgress(vsid, percent);
									}
								}

							});
						}
					});
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				try {
					_intf.setOnFileDownloadFinishedListener(new p2psvideo.aidl.OnFileDownloadFinishedListener.Stub() {
						@Override
						public void onDownloadFinished(final String vsid)
								throws RemoteException {
							_handler.post(new Runnable() {
								@Override
								public void run() {
									if (_onFileDownloadFinished != null) {
										_onFileDownloadFinished.onDownloadFinished(vsid);
									}
									if(_onFileDownloadFinisheds != null){
                                        for(OnFileDownloadFinishedListener listener:_onFileDownloadFinisheds){
                                            listener.onDownloadFinished(vsid);
                                        }
									}
								}

							});

						}
					});
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				try {
					_intf.startPullEvents();
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				if (_onServiceReady != null) {
					_onServiceReady.onServiceReady();
				}
			}
			@Override
			public void onServiceDisconnected(ComponentName arg0) {		//服务崩溃
				_intf = null;
				_svcConn = null;
				cancelAllCreateDownloadCallback();
				cancelAllReadFileCB();
				Log.e("P2PSService", "Service crash, restart in 5s");
				_handler.postDelayed(new Runnable() {
					@Override
					public void run() {
						init();
					}
				}, 5000);
			}
		};
		try {
			Intent it = new Intent(_appCtx, P2PSService.class);
			boolean r = _appCtx.bindService(it, _svcConn, Context.BIND_AUTO_CREATE);
			if (!r) {
				Log.e("P2PSService", "Bind to manager failed");
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	private static void fillFileInfo(JSONObject f, P2PSFileInfo info) throws JSONException
	{
		info.vsid = f.getString("vsid");
		info.vid = f.getString("vid");
		info.downloadPolicy = f.getInt("downloadPolicy");
		info.extra = f.getString("extra");
		info.forDownload = f.getBoolean("forDownload");
		info.forPlay = f.getBoolean("forPlay");
		info.live = f.getBoolean("live");
		info.onDiskSize = f.getLong("onDiskSize");
		info.percent = f.getInt("percent");
		info.root = f.getString("root");
		info.useTime = f.getLong("useTime");
		info.totalFileSize = f.optLong("totalFileSize", 0);
		info.duration = f.optInt("duration", 0);
		info.pformat = f.optInt("pformat", 0);
		info.format = f.optInt("format", 0);
		info.urls = f.optString("urls", "");
		info.streamers = f.optString("streamers", "");
		info.name = f.optString("name", "");
		info.tags = f.optString("tags", "");
		info.description = f.optString("description", "");
		info.page = f.optString("page", "");
		info.fromType = f.optString("fromType", "");
		info.thumbnail = f.optString("thumbnail", "");
		info.captions = f.optString("captions", "");
		info.movieLevelName = f.optString("movieLevelName", "");
		info.movieLevel = f.optInt("movieLevel", 0);
		info.rate = f.optInt("rate", 0);
		info.rateCount = f.optInt("rateCount", 0);
		JSONArray streams = f.optJSONArray("streams");
		if (streams != null) {
			int n = streams.length();
			info.streams = new P2PFileSubStreamInfo[n];
			for(int i=0; i<n; ++i) {
				P2PFileSubStreamInfo sub = new P2PFileSubStreamInfo();
				JSONObject js = streams.getJSONObject(i);
				sub.vsid = js.optString("vsid", "");
				sub.definition = js.optString("definition", "");
				sub.lang = js.optString("lang", "");
				sub.format = js.optString("format", "");
				sub.videoCodec = js.optString("videoCodec", "");
				sub.audioCodec = js.optString("audioCodec", "");
				sub.externalLink = js.optString("externalLink", "");
				sub.width = js.optInt("width", 0);
				sub.height = js.optInt("height", 0);
				sub.dataRate = js.optInt("dataRate", 0);
				sub.fps = js.optInt("fps", 0);
				info.streams[i] = sub;
			}
		}
	}
	private static String createEventId()
	{
		UUID uuid = UUID.randomUUID();
		return uuid.toString();
	}

	///判定对象是否初始化完毕
	public boolean ready()
	{
		return _intf != null;
	}

	/*!
	 * @brief 设置服务就绪回调
	 */
	public void setOnServiceReadyListener(OnServiceReadyListener l)
	{
		_onServiceReady = l;
	}

	/*!
	 * @brief 获取所有文件列表
	 */
	public boolean getFiles(List<P2PSFileInfo> files)
	{
		files.clear();
		if (_intf == null) return false;
		String r;
		try {
			r = _intf.getFiles();
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
		if (r == null || r.equals("")) return false;

		try {
			JSONObject j  = new JSONObject(r);
			JSONArray arr = j.getJSONArray("files");
			for(int i=0; i<arr.length(); ++i) {
				JSONObject f = arr.getJSONObject(i);
				P2PSFileInfo info = new P2PSFileInfo();
				fillFileInfo(f, info);
				files.add(info);
			}
			return true;
		} catch (JSONException e) {
			e.printStackTrace();
			return false;
		}
	}

	///获取单个文件信息，失败返回null
	public P2PSFileInfo getFileInfo(String vsid)
	{
		if (_intf == null) return null;
		String r;
		try {
			r = _intf.getFileInfo(vsid);
		} catch (RemoteException e) {
			e.printStackTrace();
			return null;
		}
		if (r == null || r.equals("")) return null;
		try {
			JSONObject f  = new JSONObject(r);
			P2PSFileInfo info = new P2PSFileInfo();
			fillFileInfo(f, info);
			return info;
		} catch (JSONException e) {
			e.printStackTrace();
			return null;
		}
	}

	///获取单个文件信息，失败返回null
	static public P2PSFileInfo getFileInfo(IP2PSRemote intf, String vsid)
		{
			if (intf == null) return null;
			String r;
			try {
				r = intf.getFileInfo(vsid);
			} catch (RemoteException e) {
				e.printStackTrace();
				return null;
			}
			if (r == null || r.equals("")) return null;
			try {
				JSONObject f  = new JSONObject(r);
				P2PSFileInfo info = new P2PSFileInfo();
				fillFileInfo(f, info);
				return info;
			} catch (JSONException e) {
				e.printStackTrace();
				return null;
			}
		}

	/*!
	 * @brief 设置文件列表变化通知
	 */
	public void setOnFileListChangedListener(OnFileListChangedListener l)
	{
		_onFileListChanged = l;
	}

	/*!
	 * @brief 设置文件下载进度变化通知
	 */
	public void setOnFileDownloadProgressListener(OnFileDownloadProgressListener l)
	{
		_onFileDownloadProgress = l;
	}

	/*!
	 * @brief 设置文件下载完成通知
	 */
	public void setOnFileDownloadFinishedListener(OnFileDownloadFinishedListener l)
	{
		_onFileDownloadFinished = l;
	}

    /**
     * 单列P2PMgr下防止listener被替换
     * @param l
     */
	public void addOnFileDownloadFinishedListener(OnFileDownloadFinishedListener l)
	{
        if(_onFileDownloadFinisheds == null){
            _onFileDownloadFinisheds = new ArrayList<>();
        }
        _onFileDownloadFinisheds.add(l);
    }

    /**
     * 单列P2PMgr下防止listener被替换
     * @param l
     */
    public void removeOnFileDownloadFinishedListener(OnFileDownloadFinishedListener l){
        if(_onFileDownloadFinisheds != null){
            _onFileDownloadFinisheds.remove(l);
            if(_onFileDownloadFinisheds.isEmpty()){
                _onFileDownloadFinisheds = null;
            }
        }
    }

	/*!
	 * @brief 判断文件是否存在
	 * @param vsid 视频的子流ID
	 * @return true 表示存在， false 表示不存在
	 */
	public boolean existsFile(String vsid)
	{
		if (_intf == null) return false;
		try {
			return _intf.existsFile(vsid);
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
	}

	/*!
	 * @brief 移除文件
	 * @param vsid 视频的子流ID
	 * @return true 表示移除成功， false 表示移除失败
	 */
	public boolean removeFileByID(String vsid)
	{
		if (_intf == null) return false;
		try {
			return _intf.removeFileByID(vsid);
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
	}
	/*!
	 * @brief 判断缓存目录空间是否太小 < 500MB
	 */
	public boolean cacheSpaceTooSmall()
	{
		if (_intf == null) return false;
		try {
			return _intf.cacheSpaceTooSmall();
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
	}

	/*!
	 * @brief 设置最大下载并发数
	 * @param maxDownloads 最大下载并发数 [1-16], 超出范围则忽略
	 */
	public void setMaxDownload(int maxDownloads)
	{
		if (_intf == null) return;
		try {
			_intf.setMaxDownload(maxDownloads);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	/*!
	 * @brief 获取当前最大下载并发数
	 * @return 返回当前最大下载并发数
	 */
	public int getMaxDownloads()
	{
		if (_intf == null) return 0;
		try {
			return _intf.getMaxDownloads();
		} catch (RemoteException e) {
			e.printStackTrace();
			return 0;
		}
	}
	/*!
	 * @brief 设置允许下载的策略
	 * @param allow 策略, 请参照ALLOW_DOWNLOAD_XXX
	 * 		  	0	 表示不允许下载
	 * 			1	表示在WIFI或者以太网下可以下载
	 * 			2 	表示任何网络下都可以下载
	 * @param background 是否允许后台下载
	 * 			true	表示无论应用是否在前台还是后台都按allow参数设置的策略进行下载
	 * 			false	表示当应用不在前台时不进行下载
	 * @note 判定应用是否在前台依据是是否有未关闭的P2PSMgr对象实例，如果存在未关闭的对象实例则判定为应用尚在前台
	 */
	public void allowDownload(int allow, boolean background)
	{
		if (_intf == null) return;
		try {
			_intf.allowDownload(allow, background);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	/*!
	 * @brief 获取当前下载策略
	 * @return 当前下载策略, 详情请参阅allowDownload
	 */
	public int getAllowDownload()
	{
		if (_intf == null) return 0;
		try {
			return _intf.getAllowDownload();
		} catch (RemoteException e) {
			e.printStackTrace();
			return 0;
		}
	}
	/*!
	 * @brief 获取当前是否允许后台下载
	 * @return 是否允许后台下载,  详情请参阅allowDownload
	 */
	public boolean getAllowDownloadBackground()
	{
		if (_intf == null) return false;
		try {
			return _intf.getAllowDownloadBackground();
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
	}

	/*!
	 * @brief 根据当前下载策略和当前网络状况判定当前是否允许下载
	 * @note 如果是false表明文件下载引擎目前不对数据进行下载，即使下载列表中存在未下载完成的文件
	 */
	public boolean isCurrentAllowDownload()
	{
		if (_intf == null) return false;
		try {
			return _intf.isCurrentAllowDownload();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return false;
	}

	private void sendCreateDownloadCallback(String eventId, String vsid, boolean success)
	{
		OnCreateDownload dl;
		if (eventId == null) return;
		synchronized(this) {
			dl = _downloadCallbacks.get(eventId);
			if (dl == null) return;
			_downloadCallbacks.remove(eventId);
		}
		if (success) {
			if (dl.onCreate != null) {
				dl.onCreate.onCreated(vsid);
			}
		} else {
			if (dl.onFailed != null) {
				dl.onFailed.onFailed(vsid);
			}
		}
	}

	private void removeCreateDownloadCallback(String eventId)
	{
		if (eventId == null) return;
		synchronized(this) {
			_downloadCallbacks.remove(eventId);
		}
	}

	private void cancelAllCreateDownloadCallback()
	{
		Map<String, OnCreateDownload> downloadCallbacks;
		synchronized(this) {
			downloadCallbacks = _downloadCallbacks;
			_downloadCallbacks = new HashMap<String, OnCreateDownload>();
		}
		if (downloadCallbacks == null) return;
		for (OnCreateDownload value : downloadCallbacks.values()) {
			if (value.onFailed != null) {
				value.onFailed.onFailed("");
			}
		}
	}

	private void cancelAllReadFileCB()
	{
		Map<OnHttpResponse, ReferenceCount> readFileCB;
		synchronized(this) {
			readFileCB = _readFileCB;
			_readFileCB = new HashMap<OnHttpResponse, ReferenceCount>();
		}
		if (readFileCB == null) return;
		for (OnHttpResponse value : readFileCB.keySet()) {
			value.onData(true, false, null);
		}
	}

	/*!
	@brief 创建下载
	@param urls 媒体URL
	@param streamers 串流服务器地址，通常是rtmfp协议地址
	@param opts 选项, JSON字符串格式
			vsid [可选] 要下载的子流ID，16进制，32个字符, 如果不设置则自动挑选一个子流进行下载
			video_codecs [可选] 设置播放器支持的视频解码器列表，如果不设置则默认为h.264
	@param type 下载方式, 参见DOWNLOAD_TYPE_XXX系列常量
	@param format 媒体文件格式, 目前请设置为0
	@param onCreate 创建下载成功回调
	@param onFailed 创建失败回调
	@return 如果返回false 表示下载创建失败, 返回true则表示下载任务已经提交在后台处理，是否成功不确定
	*/
	public boolean createDownload(String urls, String streamers, String opts, int type, int format, final OnFileDownloadCreatedListener onCreate, final OnFileDownloadFailedListener onFailed)
	{
		JSONObject optj = null;
		if (opts == null || opts.equals("")) {
			optj = new JSONObject();
			try {
				optj.put("event_id", createEventId());
			} catch (JSONException e) {
				e.printStackTrace();
			}
		} else {
			try {
				optj = new JSONObject(opts);
			} catch(Exception e) {
				;
			}
			if (optj == null) optj = new JSONObject();
			try {
				optj.put("event_id", createEventId());
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		final String eventId = optj.optString("event_id", "");
		opts = optj.toString();
		if (_intf == null) {
			Log.e("P2PSService", "Service is not init");
			if (onFailed != null) {
				_handler.post(new Runnable() {
					@Override
					public void run() {
						onFailed.onFailed("");
					}
				});
			}
			return false;
		}
		try {
			if (onCreate != null || onFailed != null) {
				synchronized(this) {
					OnCreateDownload dl = new OnCreateDownload();
					dl.onCreate = onCreate;
					dl.onFailed = onFailed;
					_downloadCallbacks.put(eventId, dl);
				}
			}
			return _intf.createDownload(urls, streamers, opts, type, format,
				new p2psvideo.aidl.OnFileDownloadCreatedListener.Stub() {
				@Override
				public void onCreated(final String vsid) throws RemoteException {
					Log.v("P2PSService", "Download was created: " + vsid);
					removeCreateDownloadCallback(eventId);
					if (onCreate == null) return;
					_handler.post(new Runnable() {
						@Override
						public void run() {
							onCreate.onCreated(vsid);
						}
					});
				}
			},
			new p2psvideo.aidl.OnFileDownloadFailedListener.Stub() {
				@Override
				public void onFailed(final String vsid) throws RemoteException {
					Log.e("P2PSService", "Download was failed: " + vsid);
					removeCreateDownloadCallback(eventId);
					if (onFailed == null) return;
					_handler.post(new Runnable() {
						@Override
						public void run() {
							onFailed.onFailed(vsid);
						}
					});
				}
			});
		} catch (RemoteException e) {
			e.printStackTrace();
			removeCreateDownloadCallback(eventId);
			Log.e("P2PSService", "Service exception: " + e.getMessage());
			if (onFailed != null) {
				_handler.post(new Runnable() {
					@Override
					public void run() {
						onFailed.onFailed("");
					}
				});
			}
			return false;
		}
	}

	/*!
	@brief 对已经创建的下载执行下载类型修改（取消，暂停，普通下载，尽快下载）
	@param vsid 子流ID 16进制，32个字符
	@param type 下载方式，详情请参见DOWNLOAD_TYPE_XXX系列常量
	@param downloadImd 是否立即下载
	@return 如果返回false表示vsid不存在，true 表示已经修改了下载类型
	*/
	public boolean setDownloadType(String vsid, int type, boolean downloadImd)
	{
		if (_intf == null) return false;
		try {
			return _intf.setDownloadType(vsid, type, downloadImd);
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
	}

	private void _removeReadFileCB(OnHttpResponse cb)
	{
		synchronized(this)
		{
			ReferenceCount v = _readFileCB.get(cb);
			if (v.dec() == 0) {
				_readFileCB.remove(cb);
			}
		}
	}
	/*!
	 * @brief 发出http get请求读取文件数据
	 * @param httpUrls HTTP地址，如果为空则不读取HTTP
	 * @param rtmfpUrls RTMFPGET地址，如果为空则不读取RTMFPGET
	 * @param filePath 请求的文件路径
	 * @param callbackOnMainThread 是否在主线程回调，否则在JNI线程回调结果
	 * @param cb 完成回调
	 */
	public void readHttpRtmfpFile(String httpUrls, String rtmfpUrls, String filePath, final boolean callbackOnMainThread, final OnHttpResponse cb)
	{
		if (_intf == null) {
			_handler.post(new Runnable() {
				@Override
				public void run() {
					cb.onData(true, false, null);
				}
			});
			return;
		}
		synchronized(this) {
			if (_readFileCB.containsKey(cb)) {
				ReferenceCount v = _readFileCB.get(cb);
				v.inc();
			} else {
				_readFileCB.put(cb, new ReferenceCount(1));
			}
		}
		try {
			_intf.readHttpRtmfpFile(httpUrls, rtmfpUrls, filePath, new p2psvideo.aidl.OnHttpResponse.Stub() {

				@Override
				public void onData(final boolean error, final boolean rtmfpget, final byte[] data)
						throws RemoteException {
					if (!callbackOnMainThread) cb.onData(error, rtmfpget, data);
					else {
						_handler.post(new Runnable() {
							@Override
							public void run() {
								_removeReadFileCB(cb);
								cb.onData(error, rtmfpget, data);
							}
						});
					}
				}
			});
		} catch (RemoteException e) {
			e.printStackTrace();
			_handler.post(new Runnable() {
				@Override
				public void run() {
					_removeReadFileCB(cb);
					cb.onData(true, false, null);
				}
			});
			return;
		}
	}

	/*!
	 * @brief 关闭下载对象
	 * @note 如果允许后台下载，未完成的下载任务将继续在后台下载
	 */
	public void close()
	{
		Log.v("P2PSService", "Closing P2PSMgr");
		if (_intf != null) {
			try {
				_intf.setBackground(true);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			try {
				_intf.setOnFileListChangedListener(null);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			try {
				_intf.setOnFileDownloadProgressListener(null);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			try {
				_intf.stopPullEvents();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_svcConn != null) {
			try {
				_appCtx.unbindService(_svcConn);
			} catch(Exception e) {
				e.printStackTrace();
			}
			_svcConn = null;
		}
		_intf = null;
		cancelAllCreateDownloadCallback();
	}
	///获取本地代理端口
	public int getProxyPort()
	{
		if (_intf == null) return 0;
		else
			try {
				return _intf.getProxyPort();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		return 0;
	}

	///设置是否允许p2p
	public boolean setAllowP2P(boolean allow)
	{
		if (_intf == null) return false;
		else
			try {
				_intf.setAllowP2P(allow);
				return true;
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		return false;
	}
	///获取是否允许p2p
	public boolean getAllowP2P()
	{
		if (_intf == null) return false;
		else
			try {
				return _intf.getAllowP2P();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		return false;
	}

}
